package com.bmps.springcloud.insuredmicroservice.service.underwrite.strategy.insurance;


import com.bmps.springcloud.common.utils.DateUtil;
import com.bmps.springcloud.insuredmicroservice.config.accept.ProductConfig;
import com.bmps.springcloud.insuredmicroservice.constant.accept.AcceptConstant;
import com.bmps.springcloud.insuredmicroservice.constant.accept.MultConstant;
import com.bmps.springcloud.insuredmicroservice.constant.accept.UnderWriteConstant;
import com.bmps.springcloud.insuredmicroservice.model.accept.resquest.*;
import com.bmps.springcloud.insuredmicroservice.model.underwrite.InsuredModel;
import com.bmps.springcloud.insuredmicroservice.repository.underwrite.coresystem.InsuredCoreRepository;
import com.bmps.springcloud.insuredmicroservice.service.RedisService;
import com.bmps.springcloud.insuredmicroservice.util.accept.AcceptUtil;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map;

/**
 * @author : Jacob
 * @date : 2020/3/5 13:31
 **/
public class Aat078InsuranceStrategy implements InsuranceStrategy {


    @Override
    public InsuredModel checkInsuredRolesByRiskCode(AcceptRequestDataModel acceptRequestDataModel, InsuredCoreRepository insuredCoreRepository, ProductModel productModel, ProductConfig productConfig) {
        RequestModel requestModel = acceptRequestDataModel.getRequest();
        CustInfoModel custInfoModel = requestModel.getCustInfo();
        // 健康告知为是，不允许投保
        if (this.checkInsInform(acceptRequestDataModel)){
            return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE,
                    UnderWriteConstant.UNDER_WRITE_CUSTOM_HEATH_MESSAGE);
        }

        // 产品列表
        ProductsModel productModels = requestModel.getProductInfo().getProducts();
        RedisService redisService = productConfig.getRedisService();
        InsurantModel insurantModel = this.getInsurantModel(custInfoModel.getInsurants().getInsurant(), productModel);
        if (null != insurantModel) {
            // 如果不是主险，检验主险与附加险购买份数是够一致
            if (!redisService.isMainRisk(productModel.getProdCode()) && !checkMultConsistent(productModels, productModel, redisService)) {
                return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE,
                        String.format(UnderWriteConstant.UNDER_WRITE_CUSTOM_MULT_MESSAGE, insurantModel.getName()));
            }

            // 计划1、2、3不能同时购买(当前单)
            if (!checkPlanConflict(productModels, productModel)) {
                return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE,
                        UnderWriteConstant.UNDER_WRITE_NYGG0003_MESSAGE);
            }

            // 版本计划
            Integer planVersion = productModel.getPlanVersion();
            if (null == planVersion){
                return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE,
                        UnderWriteConstant.UNDER_WRITE_CUSTOM_PLANVERSION_NOTNULL);
            }
            int years = DateUtil.getYears(insurantModel.getBirthday(), requestModel.getPolicyInfo().getCvalidate());


            // 被保人0到9岁标识
            boolean insurantFlag = 0 <= years && years <= 9;
            // 被保人61岁到70岁年龄标识
            boolean insurantYearSixtyToSeventyFlag = 61 <= years && years <= 70;

            // 购买份数
            Integer mult = productModel.getMult();
            // 被保人职业类别
            String insurantOccupation = insurantModel.getOccupationType();
            //0到9岁，只能购买计划一
            if (insurantFlag && !planVersion.equals(1)) {
                return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE, UnderWriteConstant.UNDER_WRITE_NYGG0004_MESSAGE);
            }
            if (this.checkOccupationType(insurantOccupation)) {
                return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE, String.format(UnderWriteConstant.UNDER_WRITE_NYGG0001_MESSAGE, insurantModel.getOccupationType()));
            }
            // 查询缓存
            Integer cacheMult = redisService.getCacheMult(MultConstant.GOLD, planVersion, insurantModel.getIdNo(), mult, requestModel.getPolicyInfo().getContNo());
            if (cacheMult < 0) {
                return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE,
                        UnderWriteConstant.UNDER_WRITE_NYGG0003_MESSAGE);
            }
            // 查询历史购买记录
            List<Map<String, Object>> orderMult = insuredCoreRepository.getHistoryMult(productModel.getProdCode(), insurantModel.getInsuredNo(), insurantModel.getInsuredNo());
            int queryMult = 0;
            for (Map<String, Object> map : orderMult) {
                if (planVersion != (Integer.parseInt(map.get("planVersion").toString()))) {
                    return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE,
                            UnderWriteConstant.UNDER_WRITE_NYGG0003_MESSAGE);
                } else {
                    queryMult += Integer.parseInt(String.valueOf(map.get("mult")));
                }
            }
            int sumMult = productModel.getMult() + cacheMult + queryMult;

            // 被保人61周岁-70周岁只能投保计划1，且限购一份
            // insurantYearSixtyToSeventyFlag

            // 计划一被保人职业类别限制为1-6
            if (AcceptConstant.PLAN_VERSION_ONE.equals(planVersion)) {

                // 0-9岁或者第五六类职业投保计划一，每一被保险人限购两份
                if (insurantFlag || AcceptConstant.OCCUPATION_TYPE_FIVE.equals(insurantOccupation) || AcceptConstant.OCCUPATION_TYPE_SIX.equals(insurantOccupation)) {
                    if (sumMult > 2) {
                        return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE, UnderWriteConstant.UNDER_WRITE_NYGG0005_MESSAGE);
                    }
                }
                // 61岁至70周岁，限购1份
                if (insurantYearSixtyToSeventyFlag && (sumMult > 1)){
                    return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE, UnderWriteConstant.UNDER_WRITE_NYGG0018_MESSAGE);
                }
                // 10岁级10岁以上且职业类别为1-4类，每一被保险人限购3份
                if (UnderWriteConstant.AGE_TEN_YEAR <= years && AcceptConstant.OCCUPATION_ONE_TO_FOUR.contains(insurantOccupation)) {
                    if (sumMult > 3) {
                        return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE, UnderWriteConstant.UNDER_WRITE_NYGG0006_MESSAGE);
                    }
                }
            }
            // 计划二和三被保人职业类别为1-4 每一被保险人限购一份
            if (AcceptConstant.PLAN_VERSION_TWO.equals(planVersion) || AcceptConstant.PLAN_VERSION_THREE.equals(planVersion)) {
                // 61周岁至70周岁，只能投保计划1
                if (insurantYearSixtyToSeventyFlag){
                    return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE, UnderWriteConstant.UNDER_WRITE_NYGG0017_MESSAGE);
                }
                if (!AcceptConstant.OCCUPATION_ONE_TO_FOUR.contains(insurantModel.getOccupationType())) {
                    return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE, String.format(UnderWriteConstant.UNDER_WRITE_NYGG0002_MESSAGE, insurantModel.getOccupationType()));
                }
                if (AcceptConstant.PLAN_VERSION_TWO.equals(planVersion) && sumMult > 1) {
                    return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE, UnderWriteConstant.UNDER_WRITE_NYGG0007_MESSAGE);
                }
                if (sumMult > 1) {
                    return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_FIAL_CODE, UnderWriteConstant.UNDER_WRITE_NYGG0008_MESSAGE);
                }
            }
            // 黑名单
            if (insurantModel.getBlackListFlag() > 0) {
                return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_NUGG0031,
                        String.format(UnderWriteConstant.UNDER_WRITE_NUGG0031_MESSAGE, insurantModel.getName()));
            }
            // 被保人理赔标识
            if (insurantModel.getClaimFlag() > 0) {
                return AcceptUtil.getInsuredResponse(UnderWriteConstant.UNDER_WRITE_NUGG0027,
                        String.format(UnderWriteConstant.UNDER_WRITE_NUGG0027_MESSAGE, insurantModel.getName()));
            }
        }
        return AcceptUtil.getInsuredResponse(AcceptConstant.RESULT_SUCCESS_CODE, AcceptConstant.RESULT_SUCCESS_MESSAGE);
    }


    private InsurantModel getInsurantModel(List<InsurantModel> insurantModelList, ProductModel productModel) {
        for (InsurantModel insurantModel : insurantModelList) {
            if (insurantModel.getInsSeq() == productModel.getProdInsSeq()) {
                return insurantModel;
            }
        }
        return null;
    }

    /**
     * 校验份数一致
     *
     * @param productsModel 产品列表
     * @param productModel  当前产品
     * @param redisService  缓存操作
     * @return true 一致
     */
    private Boolean checkMultConsistent(ProductsModel productsModel, ProductModel productModel, RedisService redisService) {
        for (ProductModel product : productsModel.getProduct()) {
            if (redisService.isMainRisk(product.getProdCode()) && productModel.getProdInsSeq() == product.getProdInsSeq()) {
                if (!product.getMult().equals(productModel.getMult())) {
                    return false;
                }
                break;
            }
        }
        return true;
    }

    /**
     * 校验相同产品不能存在多个计划或重复产品 且 一张保单只能为一个人购买金典守护产品
     *
     * @param productsModel 当前保单产品列表
     * @param productModel  当前产品
     * @return false - 存在多个计划
     */
    private Boolean checkPlanConflict(ProductsModel productsModel, ProductModel productModel) {
        int count = 0;
        for (ProductModel product : productsModel.getProduct()) {
            if (product.getProdCode().equals(productModel.getProdCode())) {
                count++;
            }
            if (count > 1) {
                return false;
            }
        }
        return true;
    }

    private Boolean checkOccupationType(String insurantOccupation) {
        // 职业校验1-6
        return !AcceptConstant.OCCUPATION_ONE_TO_SIX.contains(insurantOccupation);
    }

    /**
     * 校验受理报文被保人是否存在健康告知
     *
     * @param acceptRequestDataModel 受理请求报文
     * @return true-存在 false-不存在
     */
    private boolean checkInsInform(AcceptRequestDataModel acceptRequestDataModel) {
        List<InsurantModel> insurantModels = acceptRequestDataModel.getRequest().getCustInfo().getInsurants().getInsurant();
        for (InsurantModel insurantModel : insurantModels) {
            if (StringUtils.equals(AcceptConstant.STRING_Y, insurantModel.getInsInform())) {
                return true;
            }
        }
        return false;
    }
}
